package we.caro;

public class CaroGame {
    public int getTurn() {
        return turn;
    }

    public int getFirstMove() {
        return firstMove;
    }

    public void setStopped(boolean stopped) {
        this.stopped = stopped;
    }

    public boolean isStopped() {
        return stopped;
    }

    public enum RESULT {
        PLAYER_ONE_WIN,
        PLAYER_TWO_WIN,
        DRAW,
        CONTINUE,
        ERROR,
        STOPPED
    }
    private final int TABLE_SIZE = 15;
    private final int TABLE_AMOUNT = TABLE_SIZE * TABLE_SIZE;
    private final int BLACK = 1;
    private final int WHITE = 2;
    private final int EMPTY = -1;
    //private int currentPlayer;
    private int[][] board = new int[TABLE_SIZE][TABLE_SIZE];
    private int win_r1, win_c1, win_r2, win_c2;
    private int number_move = 0;    


    private int playerOne, playerTwo;
    private int firstMove; // nguoi di dau tien
    private int turn;

    public CaroGame(int playerOne, int playerTwo) {
        super();
        this.playerOne = playerOne;
        this.playerTwo = playerTwo;        
        newGame(playerOne);
    }

    boolean readyOne = false;
    boolean readyTwo = false;

    public boolean isStarted() {
        return (readyOne && readyTwo);
    }

    public void ready(int player) {
        if (isStarted())
            return;

        if (player == playerOne)
            readyOne = true;
        else if (player == playerTwo)
            readyTwo = true;
    }


    public void newGame(int firstMover) {
        turn = firstMover;
        this.firstMove = firstMove;
        readyOne = false;
        readyTwo = false;
      for (int i = 0; i < TABLE_SIZE; i++)
          for (int j = 0; j < TABLE_SIZE; j++) {
              board[i][j] = EMPTY;
          }
    }
    
    private boolean stopped = false;

    public RESULT move(int who, int place) {
        return RESULT.PLAYER_ONE_WIN;
        //return RESULT.DRAW;
    }
    
    public RESULT move1(int who, int place) {
        if (stopped)
            return RESULT.STOPPED;
        if (place >= TABLE_AMOUNT) // sai vi tri
            return RESULT.ERROR;
        int row;
        int column;
        if (who == turn) {
            row = place / TABLE_SIZE;
            column = place % TABLE_SIZE;
            if (board[row][column] == EMPTY) {
                if (who == playerOne) {
                    board[row][column] = BLACK;
                    turn = playerTwo;
                } else {
                    board[row][column] = WHITE;
                    turn = playerOne;
                }
                number_move++;
                return result(row, column);
            }
            else
                return RESULT.ERROR;
        }
        else 
            return RESULT.ERROR;                          
    }

    public boolean draw() {
        return number_move >= TABLE_AMOUNT;
    }

    private RESULT result(int row, int col) {
        // This is called just after a piece has been played on the
        // square in the specified row and column. It determines
        // whether that was a winning move by counting the number
        // of squares in a line in each of the four possible
        // directions from (row,col). If there are 5 squares (or more)
        // in a row in any direction, then the game is won.

        if (win(board[row][col], row, col, 1, 0)) {
            if (board[row][col] == BLACK)
                return RESULT.PLAYER_ONE_WIN;
            if (board[row][col] == WHITE)
                return RESULT.PLAYER_TWO_WIN;
        }
        if (win(board[row][col], row, col, 0, 1)) {
            if (board[row][col] == BLACK)
                return RESULT.PLAYER_ONE_WIN;
            if (board[row][col] == WHITE)
                return RESULT.PLAYER_TWO_WIN;
        }

        if (win(board[row][col], row, col, 1, -1)) {
            if (board[row][col] == BLACK)
                return RESULT.PLAYER_ONE_WIN;
            if (board[row][col] == WHITE)
                return RESULT.PLAYER_TWO_WIN;
        }

        if (win(board[row][col], row, col, 1, 1)) {
            if (board[row][col] == BLACK)
                return RESULT.PLAYER_ONE_WIN;
            if (board[row][col] == WHITE)
                return RESULT.PLAYER_TWO_WIN;
        }

        /*
       * When we get to this point, we know that the game is not won. The
       * value of win_r1, which was changed in the count() method, has to be
       * reset to -1, to avoid drawing a red line on the board.
       */

        if (draw())
            return RESULT.DRAW;
        else{
          win_r1 = -1;
          return RESULT.CONTINUE; // tiep tuc
        }
    } // end winner()

    private boolean win(int player, int row, int col, int dirX, int dirY) {
        // Counts the number of the specified player's pieces starting at
        // square (row,col) and extending along the direction specified by
        // (dirX,dirY). It is assumed that the player has a piece at
        // (row,col). This method looks at the squares (row + dirX, col+dirY),
        // (row + 2*dirX, col + 2*dirY), ... until it hits a square that is
        // off the board or is not occupied by one of the players pieces.
        // It counts the squares that are occupied by the player's pieces.
        // Furthermore, it sets (win_r1,win_c1) to mark last position where
        // it saw one of the player's pieces. Then, it looks in the
        // opposite direction, at squares (row - dirX, col-dirY),
        // (row - 2*dirX, col - 2*dirY), ... and does the same thing.
        // Except, this time it sets (win_r2,win_c2) to mark the last piece.
        // Note: The values of dirX and dirY must be 0, 1, or -1. At least
        // one of them must be non-zero.


        int ct = 1; // Number of pieces in a row belonging to the player.

        int r, c; // A row and column to be examined

        r = row + dirX; // Look at square in specified direction.
        c = col + dirY;
        while (r >= 0 && r < TABLE_SIZE && c >= 0 && c < TABLE_SIZE && board[r][c] == player) {
            // Square is on the board and contains one of the players's pieces.
            ct++;
            r += dirX; // Go on to next square in this direction.
            c += dirY;
        }

        win_r1 = r - dirX; // The next-to-last square looked at.
        win_c1 = c - dirY; // (The LAST one looked at was off the board or
        // did not contain one of the player's pieces.

        r = row - dirX; // Look in the opposite direction.
        c = col - dirY;
        while (r >= 0 && r < TABLE_SIZE && c >= 0 && c < TABLE_SIZE && board[r][c] == player) {
            // Square is on the board and contains one of the players's pieces.
            ct++;
            r -= dirX; // Go on to next square in this direction.
            c -= dirY;
        }

        win_r2 = r + dirX;
        win_c2 = c + dirY;

        // At this point, (win_r1,win_c1) and (win_r2,win_c2) mark the endpoints
        // of the line of pieces belonging to the player.

        return (ct == 5);

    } // end count()

    public int getPlayerOne() {
        return playerOne;
    }

    public int getPlayerTwo() {
        return playerTwo;
    }
}
